#include <memory>
#include <cstdlib>
#include <cstring>
#include <iostream>

extern "C" {
#include "skynet.h"
#include "skynet_handle.h"
#include "skynet_module.h"
}

class MyService {
public:
    MyService() : ctx_(nullptr) {}
    ~MyService() {
        skynet_error(ctx_, "MyService released");
    }

    bool init(struct skynet_context* ctx, const char* params) {
        ctx_ = ctx;
        skynet_error(ctx_, "MyService initialized with params: %s", params);
        return true;
    }

    void signal(int signal) {
        skynet_error(ctx_, "MyService received signal: %d", signal);
    }

    int callback(int type, int session, uint32_t source, const void* msg, size_t sz) {
        skynet_error(ctx_, "MyService received message from :%08x, type : %d, session = %d", source, type, session);
        return 0;
    }

private:
    struct skynet_context* ctx_;
};

extern "C" {

struct MyServiceWrapper {
    std::unique_ptr<MyService> instance;
};

static int simpleservice_cb(struct skynet_context* ctx, void* ud, int type, int session, uint32_t source, const void* msg, size_t sz) {
    MyServiceWrapper* self = static_cast<MyServiceWrapper*>(ud);
    return self->instance->callback(type, session, source, msg, sz);
}

void* simpleservice_create() {
    auto* self = new MyServiceWrapper;
    self->instance = std::make_unique<MyService>();
    return self;
}

int simpleservice_init(void* inst, struct skynet_context* ctx, const char* params) {
    MyServiceWrapper* self = static_cast<MyServiceWrapper*>(inst);
    skynet_callback(ctx, self, simpleservice_cb);
    return self->instance->init(ctx, params) ? 0 : 1;
}

void simpleservice_release(void* inst) {
    MyServiceWrapper* self = static_cast<MyServiceWrapper*>(inst);
    delete self;
}

void simpleservice_signal(void* inst, int signal) {
    MyServiceWrapper* self = static_cast<MyServiceWrapper*>(inst);
    self->instance->signal(signal);
}

}
